package org.kangjia.utils;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 文件操作工具类
 * @author ren
 * @description
 * @date 2022年03月11日 09:33:01
 */
public class FileUtils {

	/**
	 * 下载文件到response
	 * @param file
	 * @param response
	 * @param fileName
	 */
	public static boolean downFileToResponse(File file, HttpServletResponse response, String fileName){
		boolean flag;
		InputStream is = null;
		OutputStream os = null;
		try {
			is = new FileInputStream(file);
			os = response.getOutputStream();
			if(fileName != null){
				fileName = URLEncoder.encode(fileName, "UTF-8");
			}else{
				fileName = file.getName();
			}
			response.setHeader("Content-disposition", "attachment; filename="+fileName);

			byte[] b = new byte[2048];
			int len;
			while ((len = is.read(b)) != -1) {
				os.write(b, 0, len);
			}

			os.flush();
			flag = true;
		} catch (Exception e) {
			flag = false;
			e.printStackTrace();
		} finally {
			if(is != null){
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(os != null){
				try {
					os.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return flag;
	}

	/**
	 * 拷贝文件到某处
	 * @param file 			上传的文件
	 * @param outPath 	文件保存路径
	 * @return
	 * @throws Exception
	 */
	public static boolean copyFile(File file, String outPath){
		boolean flag;
		InputStream is = null;
		FileOutputStream os = null;
		try {
			File newFile = new File(outPath);
			is = new FileInputStream(file);
			os = new FileOutputStream(newFile);

			byte[] b = new byte[2048];
			int len;
			while ((len = is.read(b)) != -1) {
				os.write(b, 0, len);
			}

			os.flush();
			flag = true;
		} catch (IOException e) {
			flag = false;
			e.printStackTrace();
		} finally {
			if(is != null){
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(os != null){
				try {
					os.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return flag;
	}

	/**
	 * 文件转二进制流
	 * @param file
	 * @return
	 */
	public static byte[] fileToByte(File file){
		byte[] buffer = null;
		InputStream is = null;
		ByteArrayOutputStream os = null;
		try {
			is = new FileInputStream(file);
			os = new ByteArrayOutputStream();
			byte[] b = new byte[2048];
			int n;
			while ((n = is.read(b)) != -1) {
				os.write(b, 0, n);
			}
			is.close();
			buffer = os.toByteArray();
		}catch (Exception e){
			e.printStackTrace();
		}finally {
			if(is != null){
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(os != null){
				try {
					os.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return buffer;
	}

	/**
	 * 读取文件内容到字符串
	 * @param file			读取的文件
	 * @param isNewLine		是否换行
	 * @return
	 */
	public static String readFile(File file, boolean isNewLine){
		StringBuffer sb = new StringBuffer();
		BufferedReader br = null;
		String s;
		try {
			br = new BufferedReader(new FileReader(file));
			while ((s =br.readLine()) != null) {
				sb.append(s + (isNewLine?"\n":""));
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(br != null){
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return sb.toString();
	}

	/**
	 * 按行读取文件内容到字符串集合
	 * @param file
	 * @return
	 */
	public static List<String> readFile(File file){
		List<String> list = new ArrayList<String>();
		BufferedReader br = null;
		String s;
		try {
			br = new BufferedReader(new FileReader(file));
			while ((s =br.readLine()) != null) {
				list.add(s);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(br != null){
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return list;
	}

	/**
	 * 递归删除某文件，包含文件及文件夹
	 * @param file
	 * @return
	 */
	public static boolean deleteFile(File file){
        if (file.isDirectory()) {
            String[] children = file.list();
            for (int i = 0; i < children.length; i++) {
                if (!deleteFile(new File(file, children[i]))) {
                    return false;
                }
            }
        }
        //删除空文件夹
        return file.delete();
	}

	/**
	 * 计算某文件或文件夹的大小
	 * @param file
	 * @return
	 */
	public static Long calculateFileSize(File file){
		Long size = 0l;
		if (file.isDirectory()) {
			String[] children = file.list();
			for (int i = 0; i < children.length; i++) {
				size += calculateFileSize(new File(file, children[i]));
			}
		}else{
			size = file.length();
		}
		return size;
	}

	/**
	 *获取文件名
	 * @param file
	 * @param hasSuffix
	 * @return
	 */
	public static String getFileName(File file, boolean hasSuffix){
		String name = file.getName();
		if(!hasSuffix){
			name = name.substring(0,name.lastIndexOf("."));
		}
		return name;
	}

	/**
	 *获取文件后缀
	 * @param file
	 * @return
	 */
	public static String getFileSuffix(File file){
		String fileName = getFileName(file, true);
		return fileName.substring(fileName.lastIndexOf(".")+1);
	}

	/**
	 * 在某目录下按年月日构建目录
	 * @param filePath
	 * @return
	 */
	public static void createYMDDirectory(String filePath){
		Calendar c = Calendar.getInstance();
		List<String> list = new ArrayList<String>();
		list.add(0,c.get(Calendar.YEAR)+"");
		list.add(1,c.get(Calendar.MONTH)+1+"");
		list.add(2,c.get(Calendar.DAY_OF_MONTH)+"");
		File f;
		for(int i = 0;i < 3; i++){
			f = new File(filePath + File.separator + list.get(i));
			if(!f.exists()){
				f.mkdirs();
			}
			filePath = f.getAbsolutePath();
		}
	}

	/**
	 * 按正则删除文件中的某几行数据
	 * @param file		文件
	 * @param regular	正则表达式
	 * @return
	 */
	public static List<String> removeFileLines(File file,String regular){
		List<String> clearList = new ArrayList<String>();
		List<String> tempList = new ArrayList<String>();
		RandomAccessFile raf = null;
		try {
			Pattern pattern = Pattern.compile(regular);
			raf = new RandomAccessFile(file, "rw");
			String line;
			while ((line = raf.readLine()) != null && raf.getFilePointer() <= raf.length()) {
				Matcher matcher = pattern.matcher(line);
				if(matcher.find()){
					clearList.add(line);
				}else{
					tempList.add(line);
				}
			}
			//重新定位光标
			raf.seek(0);
			//清空文件内容
			raf.setLength(0);
			for (int i=0;i<tempList.size();i++){
				line = tempList.get(i) + (i == tempList.size()-1 ? "":"\n");
				raf.write(line.getBytes());
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try{
				if(raf != null){
					raf.close();
				}
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		return clearList;
	}

	/**
	 * 删除文件中的前几行
	 * @param file
	 * @param lineNum
	 * @return
	 * @throws IOException
	 */
	public static List<String> removeFileFirstLines(File file, int lineNum){
		List<String> strList = new ArrayList<String>();
		RandomAccessFile raf = null;
		try{
			raf = new RandomAccessFile(file, "rw");
			//定位最初要写入的位置
			long writePosition = raf.getFilePointer();
			for (int i = 0 ; i < lineNum ; i++){
				String line = raf.readLine();
				if(line == null){
					break;
				}
				strList.add(line);
			}
			// 下一行向上移
			long readPosition = raf.getFilePointer();

			byte[] buff = new byte[2048];
			int n;
			while (-1 != (n = raf.read(buff))) {
				raf.seek(writePosition);
				raf.write(buff, 0, n);
				readPosition += n;
				writePosition += n;
				raf.seek(readPosition);
			}
			raf.setLength(writePosition);
		} catch(IOException e){
			e.printStackTrace();
		} finally{
			try{
				if(raf != null){
					raf.close();
				}
			}catch(IOException e){
				e.printStackTrace();
			}
		}

		return strList;
	}

	/**
	 * 删除文件中的哪几行数据
	 * @param file		文件
	 * @param lines		行号集合
	 * @return
	 */
	public static List<String> removeFileLines(File file,List<Long> lines){
		List<String> clearList = new ArrayList<String>();
		List<String> tempList = new ArrayList<String>();
		long num = 0l;
		RandomAccessFile raf = null;

		try {
			raf = new RandomAccessFile(file, "rw");
			String line;
			while ((line = raf.readLine()) != null && raf.getFilePointer() <= raf.length()) {
				if(lines.contains(++num)){
					clearList.add(line);
				}else{
					tempList.add(line);
				}
			}
			//重新定位光标
			raf.seek(0);
			//清空文件内容
			raf.setLength(0);
			for (int i=0;i<tempList.size();i++){
				line = tempList.get(i) + (i == tempList.size()-1 ? "":"\n");
				raf.write(line.getBytes());
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try{
				if(raf != null){
					raf.close();
				}
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		return clearList;
	}

	/**
	 * 删除文件中的从几行到几行数据（不包含结束行）
	 * @param file		文件
	 * @param startLine	开始行号
	 * @param endLine	结束行号
	 * @return
	 */
	public static List<String> removeFileLines(File file,Long startLine,Long endLine){
		List<String> clearList = new ArrayList<String>();
		List<String> tempList = new ArrayList<String>();
		RandomAccessFile raf = null;
		long num = 0l;
		try {
			raf = new RandomAccessFile(file, "rw");
			String line;
			while ((line = raf.readLine()) != null && raf.getFilePointer() <= raf.length()) {
				++num;
				if(startLine.longValue() <= num && endLine.longValue() > num){
					clearList.add(line);
				}else{
					tempList.add(line);
				}
			}
			//重新定位光标
			raf.seek(0);
			//清空文件内容
			raf.setLength(0);
			for (int i=0;i<tempList.size();i++){
				line = tempList.get(i) + (i == tempList.size()-1 ? "":"\n");
				raf.write(line.getBytes());
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try{
				if(raf != null){
					raf.close();
				}
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		return clearList;
	}

}
